
                  . vs . (Dr.Web vs AVP):
                          Programmer's Competition

                                                  
                                                  ...

                      
              -
 .         , 
 :        (       
   4.20)        IDIV,      
    .
     H    .
           DIV   IDIV,   --
     . H    ,  
   AX    DX:AX   EDX:EAX,  ,   ,
          .           
     AL:AH, AX:DX  EAX:EDX.  
           ,  
   ,           
      (EXCEPTION_INT_OVERFLOW)                 0
 (EXCEPTION_INT_DIVIDE_BY_ZERO).
     ,      ,         DIV     IDIV  
     ,       
  ,     .
               .

=============================================================================
   - : drweb32.dll
=============================================================================

emul_flags      = ebp

--------------------------------------------------------------------web/div8-

emul_div8:      mov     ecx, edx        ; cl = 
                and     ecx, 0FFh
                ;;
                mov     eax, emul_eax   ;   
                and     eax, 0FFFFh     ; AX = 
                ;;
                or      ecx, ecx        ;   0 ?
                jz      emul_div0
                cmp     ah, cl          ;    >= 
                jae     emul_div0
                ;;
                xor     edx, edx        ;   
                ;;
                push    emul_flags      ;  
                popf
                div     cx
                pushf
                pop     emul_flags
                ;;
                cmp     eax, 0FFh       ;   
                ja      emul_div0
                ;;
                mov     emul_al, al     ;   
                mov     emul_ah, dl
                ;;
                jmp     emul_complete

-------------------------------------------------------------------web/div16-

emul_div16:     mov     ecx, edx        ; cx <- 
                and     ecx, 0FFFFh
                ;;
                mov     eax, emul_eax   ;   
                and     eax, 0FFFFh     ; DX:AX = 
                mov     edx, emul_edx
                and     edx, 0FFFFh
                ;;
                or      ecx, ecx        ;   0 ?
                jz      emul_div0
                cmp     edx, ecx        ;    >= 
                jae     emul_div0
                ;;
                shl     edx, 10h        ;   
                mov     dx, ax          ; EDX:EAX <-- dx:ax
                mov     eax, edx
                xor     edx, edx
                ;;
                push    emul_flags      ;  
                popf
                div     ecx
                pushf
                pop     emul_flags
                ;;
                cmp     eax, 0FFFFh     ;   
                ja      emul_div0
                ;;
                mov     emul_ax, ax     ;   
                mov     emul_dx, dx
                ;;
                jmp     emul_complete

-------------------------------------------------------------------web/div32-

emul_div32:     mov     ecx, edx        ; ecx <- 
                ;;
                mov     eax, emul_eax   ;   
                mov     edx, emul_edx   ; EDX:EAX = 
                ;;
                or      edx, edx        ;  .  EAX   ?
                jz      emul_complete   ;    .
                ;
                or      ecx, ecx        ;   0 ?
                jz      emul_div0
                cmp     edx, ecx        ;    >= 
                jae     emul_div0
                ;;
                push    emul_flags      ;  
                popf
                div     ecx
                pushf
                pop     emul_flags
                ;;
                mov     emul_eax, eax   ;   
                mov     emul_edx, edx
                ;;
                jmp     emul_complete

-------------------------------------------------------------------web/idiv8-

emul_idiv8:     movsx   ecx, dl         ; cl = dl = 
                ;;
                mov     ax, emul_ax     ;   
                ;;                      ; AX = 
                or      ecx, ecx        ;   0 ?
                jz      emul_div0
                ;;
                test    dl, 80h         ;    (dl)
                jz      @@1
                neg     dl
@@1:            ;;
                test    ah, 80h         ;    (ah)
                jz      @@2             ; AH =   
                neg     ah
@@2:            ;;
                sub     dl, ah          ; dl <= ah * 2
                jb      emul_div0
                cmp     dl, ah
                jbe     emul_div0
                ;;
                sub     dl, ah          ; dl - ah * 2 != 1
                cmp     dl, 1
                jnz     @@3
                test    al, 80h         ; ,  , ?
                jnz     emul_div0
@@3:            ;;
                mov     ax, emul_ax     ;   
                cwd                     ; DX:AX <-- AX
                ;;
                push    emul_flags      ;  
                popf
                idiv    cx
                pushf
                pop     emul_flags
                ;;
                cmp     ax, 7Fh         ;   
                ja      emul_div0
                ;;
                mov     emul_al, al     ;   
                mov     emul_ah, dl
                ;;
                jmp     emul_complete

------------------------------------------------------------------web/idiv16-

emul_idiv16:    movsx   ecx, dx         ; ecx = dx = 
                ;;
                mov     ax, emul_dx     ; ax =   
                ;;
                or      ecx, ecx        ;   0 ?
                jz      emul_div0
                ;;
                test    dh, 80h         ;    (dx)
                jz      @@1
                neg     dx
@@1:            ;;
                test    ah, 80h         ;    (ax)
                jz      @@2
                neg     ax
@@2:            ;;
                sub     dx, ax          ; if (dx <= ax * 2) div0
                jb      emul_div0
                cmp     dx, ax
                jbe     emul_div0
                ;;
                sub     dx, ax          ; if (dx - ax * 2) != 1 { ...
                cmp     dx, 1
                jnz     @@3
                test    emul_ah, 80h    ;   ,  
                jnz     emul_div0       ; ?
@@3:            ;;
                mov     eax, emul_eax   ;   
                and     eax, 0FFFFh
                mov     edx, emul_edx
                and     edx, 0FFFFh
                ;;
                or      ecx, ecx        ;   0 ?
                jz      emul_div0       ;  ,  
                ;;
                shl     edx, 10h        ;   
                mov     dx, ax          ; EDX:EAX <-- dx:ax
                mov     eax, edx
                cdq
                ;;
                push    emul_flags      ;  
                popf
                idiv    ecx
                pushf
                pop     emul_flags
                ;;
                cmp     eax, 7FFFh      ;   
                ja      emul_div0
                ;;
                mov     emul_ax, ax     ;   
                mov     emul_dx, dx
                ;;
                jmp     emul_complete

------------------------------------------------------------------web/idiv32-

emul_idiv32:    mov     emul_eax, 0     ;   
                mov     emul_edx, 0
                ;;
                jmp     emul_complete

-----------------------------------------------------------------------------

=============================================================================
   - (,    ) : kernel.avc/emul.obj
=============================================================================

divisor         =       ebx

--------------------------------------------------------------------avp/div8-

emul_div8:      cmp     byte ptr [divisor], 0   ;   0 ?
                jz      emul_int0
                ;;
                mov     ax, emul_ax     ;   
                ;;                      ; AX = 
                cmp     ah, [divisor]   ;    => 
                jae     try_emul_int0
                ;;
                push    emul_flags      ;  
                popfw
                div     byte ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_ax, ax     ;   
                ;;
                jmp     emul_complete

-------------------------------------------------------------------avp/div16-

emul_div16:     cmp     word ptr [divisor], 0   ;   0 ?
                jz      emul_int0
                ;;
                mov     ax, emul_ax     ;   
                mov     dx, emul_dx     ; DX:AX = 
                ;;
                cmp     dx, [divisor]   ;    => 
                jae     try_emul_int0
                ;;
                push    emul_flags      ;  
                popfw
                div     word ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_ax, ax     ;   
                mov     emul_dx, dx
                ;;
                jmp     emul_complete

-------------------------------------------------------------------avp/div32-

emul_div32:     cmp     dword ptr [divisor], 0  ;   0 ?
                jz      emul_int0
                ;;
                mov     eax, emul_eax   ;   
                mov     edx, emul_edx   ; EDX:EAX = 
                ;;
                cmp     edx, [divisor]  ;    => 
                jae     try_emul_int0
                ;;
                push    emul_flags      ;  
                popfw
                div     dword ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_eax, eax   ;   
                mov     emul_edx, edx
                ;;
                jmp     emul_complete

-------------------------------------------------------------------avp/idiv8-

emul_idiv8:     cmp     byte ptr [divisor], 0   ;   0 ?
                jz      emul_int0
                ;;
                mov     ax, emul_ax     ;   
                ;;                      ; AX = 
                cmp     ax, 80h         ;  >= 80h
                jae     emul_complete
                ;;
                push    emul_flags      ;  
                popfw
                idiv    byte ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_ax, ax     ;   
                ;;
                jmp     emul_complete

------------------------------------------------------------------avp/idiv16-

emul_idiv16:    cmp     word ptr [divisor], 0   ;   0 ?
                jz      emul_int0
                ;;
                mov     ax, emul_ax     ;   
                mov     dx, emul_dx     ; DX:AX = 
                ;;
                cmp     dx, 0           ;    = 0
                jnz     emul_complete
                cmp     ax, 8000h       ;    >= 8000h
                jae     emul_complete
                ;;
                push    emul_flags      ;  
                popfw
                idiv    word ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_ax, ax     ;   
                mov     emul_dx, dx
                ;;
                jmp     emul_complete

------------------------------------------------------------------avp/idiv32-

emul_idiv32:    cmp     dword ptr [divisor], 0  ;   0 ?
                jz      emul_int0
                ;;
                mov     eax, emul_eax   ;   
                mov     edx, emul_edx   ; EDX:EAX = 
                ;;
                cmp     edx, 0          ;    = 0
                jnz     emul_complete
                cmp     eax, 80000000h  ;     2^31
                jae     emul_complete
                ;;
                push    emul_flags      ;  
                popfw
                idiv    dword ptr [divisor]
                pushfw
                pop     emul_flags
                ;;
                mov     emul_eax, eax   ;   
                mov     emul_edx, edx
                ;;
                jmp     emul_complete

-----------------------------------------------------------------------------

  H ,   .
  ,     .

   12  100%   
     5-. , ,     ,
         .
          
     .

  1.  div8  div16

  :  ;
             

  :  ,   ,  ,
                  ,    ;
                

            ,     :
            (   ,    - ),
                 ?   .

  2.  div32

  :  ;
             

  :         ,
             - ,   - -   .

            ,    -    
               ...   .

  3.  idiv8

  :  .
                128 (  65536),
               

  :   ,
                  ,
               .

            ,  AX=C0FF , , CL=81,
             IDIV  ,
                 INT0

  4.  idiv16

  :  .
                32768 (  2^32),
               

  :    ;
             ,
              ,    ,
                 ;

            ,  DX=C000, AX=FFFF, , , CX=8001,
             IDIV  ,
                 INT0

  5.  idiv32

  :  ,
                  80000000h,   2^64,
                

  :    .

-----------------------------------------------------------------------------

       .

          IDIV    . 
  - ,   .

            :        
                  6         6           3           3
                   6         5           2           3

     ,      ,     :  
     ,   ,    
 ;         ,    , 
      ,   -    -  
   IDIV-.
             IDIV-,  ,  - 
  -    -  . H    .
           ,  ,     ,
     1%         
   .

-----------------------------------------------------------------------------

      ,  !

      1.
     ,  ,     ,   
 ,        .  H    -  .    ,
 -,      ,   
 ,  ,            
  ,      ( - ),  
 /,   ... ,   ...  ,  
      H  ,      ,    ,
       ,  ,      ,
     ,   .  ...   
 ... , ,       ...
      2.
       ,      ,   ,
     ,         . 
 :      .   ,  
  ,   ,      
 ,           
  .  .

-----------------------------------------------------------------------------

       ,     .
        ,     ,   
  IDIV ( ),     KME.
           ,  ,    
   ...     ,      
   .
          IDIV .  ?

-----------------------------------------------------------------------------

 ,   IDIV,  CF=1  INT0.

 ; input:  EDX:EAX = 
 ;         ECX = 
 ; output: CF = 0 --  , EAX = , EDX = 
 ;         CF = 1 --  (0  )

emul_idiv:              pusha
                        xor     bh, bh
                        or      ecx, ecx
                        jz      __div_err
                        jg      __g1
                        neg     ecx
                        or      bh, 1
__g1:                   or      edx, edx
                        jge     __g2
                        neg     edx
                        neg     eax
                        sbb     edx, 0
                        xor     bh, 3
__g2:                   xor     esi, esi        ; d
                        xor     edi, edi        ; m
                        mov     bl, 64
__divcycle:             shl     esi, 1          ; d <<= 1
                        jc      __div_err
                        shl     eax, 1          ; x <<= 1
                        rcl     edx, 1
                        rcl     edi, 1          ; m = (m << 1) | x.bit[i]
                        jc      __cmpsub
                        cmp     edi, ecx
                        jb      __cmpsubok
__cmpsub:               sbb     edi, ecx
                        or      esi, 1
__cmpsubok:             dec     bl
                        jnz     __divcycle
                        or      esi, esi
                        js      __div_err
                        or      edi, edi
                        js      __div_err
                        test    bh, 1
                        jz      __skipneg1
                        neg     esi
__skipneg1:             test    bh, 2
                        jz      __skipneg2
                        neg     edi
__skipneg2:             mov     [esp+7*4], esi
                        mov     [esp+5*4], edi
                        popa
                        clc
                        retn
__div_err:              popa
                        stc
                        retn

-----------------------------------------------------------------------------

 H    ...    ?

                                                            (x) 2000 Z0MBiE
                                                      http://z0mbie.host.sk

-----------------------------------------------------------------------------
